package com.wutong.eams.controller;

import com.wutong.eams.config.JwtConfig;
import com.wutong.eams.dto.AuthenticDTO;
import com.wutong.eams.entity.User;
import com.wutong.eams.enums.Role;
import com.wutong.eams.utils.JwtUtil;
import com.wutong.eams.utils.RedisUtil;
import com.wutong.eams.utils.RouterUtil;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.Map;

@Slf4j
@WebServlet("/api/auth/*")  // 路由配置，匹配 /api/auth 下的请求
public class AuthenticController extends BaseController {

    @Override
    public Role getPermission() {
        return Role.ADMIN;
    }

    @Override
    public boolean needPermission() {
        return true;
    }

    @Override
    public Map<String, RouterUtil.MatchType> getWhiteList() {
        return Map.of(
                "/api/auth/login", RouterUtil.MatchType.EXACT
        );
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
        // 获取用户信息
        // 需要设置Authorization请求头为JWT token
        // Filter验证Token有效性

        // 判断路由是否为/api/auth/login
        if (hasCurrentRule("/info", req, resp)) {
            User user = getUserAuthenticService().getUserInfo((String) req.getSession().getAttribute("username"));
            if (user == null) {
                // 用户不存在，返回错误信息
                log.error("用户不存在");
                resp.setStatus(401);
            } else {
                // 用户存在，返回用户信息
                resp.setStatus(200);
                req.setAttribute("user", user);
            }
        } else if (hasCurrentRule("/logout", req, resp)) {
            doDelete(req, resp);
        } else {
            resp.setStatus(404);
            log.error("路由不存在");
            viewForward("/page/login", req, resp);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doPost(req, resp);
        // 执行登录接口
        // 需要设置Authorization请求头为JWT token
        // 登录成功后，返回JWT token
        // 登录失败后，返回错误信息

        if (!hasCurrentRule("/login", req, resp)) {
            return;
        }

        // 获取登录参数，用户名，密码
        String username = req.getParameter("username");
        String password = req.getParameter("password");

        // 调用登录服务，验证用户名密码
        User user = getUserAuthenticService().login(new AuthenticDTO.LoginDTO(username, password));
        if (user == null) {
            // 登录失败，返回错误信息
            resp.setStatus(401);
            routerRedirect("/page/login", req, resp);
        } else {
            // 像session中添加用户信息
            req.getSession().setAttribute("user", user);
            // 登录成功，返回JWT token
            String token = JwtUtil.generateToken("LOGIN_TOKEN-" + user.getUsername(), Map.of(
                    "userId", user.getUserId(),
                    "username", user.getUsername(),
                    "role", user.getRole(),
                    "status", user.getStatus()
            ), JwtConfig.EXPIRATION_TIME);
            // 将token 添加进Redis缓存
            if (RedisUtil.getValue("LOGIN_TOKEN-" + user.getUsername(), String.class) == null) {
                RedisUtil.setValue("LOGIN_TOKEN-" + user.getUsername(), token, JwtConfig.EXPIRATION_TIME);
            }
            // 并设置Authorization响应头
            resp.setStatus(200);
            routerRedirect("/page/main", req, resp);
        }
    }

    @Override
    protected void doDelete(HttpServletRequest req, HttpServletResponse resp) throws IOException, ServletException {
        super.doDelete(req, resp);
        // 由Filter处理Token，验证Token有效性
        // 需要在这里注销Token，并返回成功信息

        if (!hasCurrentRule("/logout", req, resp)) {
            return;
        }

        String key = "LOGIN_TOKEN-" + req.getSession().getAttribute("username");
        String result = RedisUtil.getValue(key, String.class);
        if (result == null) {
            // Token已过期，返回错误信息
            resp.setStatus(401);
            log.error("Token已过期");
        } else {
            // 注销Token，并返回成功信息
            RedisUtil.removeValue(key);
            resp.setStatus(200);
            log.info("注销Token成功");
        }
        viewForward("/page/login", req, resp);
    }
}
